﻿using System.Collections.Generic;
using Framework;
using UnityEngine;

namespace Game
{
    public class SceneLayerEntity : CommonEntity
    {
        private GameObject _gameObject;
        private Transform _transform;
        private int _startOrder;
        private int _curringOrder;
        private Bounds _sceneBounds;

        private List<ISceneObjectEntity> _sceneObjectList;
        private List<ISceneObjectEntity> _toRemoveSceneObjectList;
        private Transform _trackCameraTransform;
        
        public SceneLayerEntity(Transform transform)
        {
            _transform = transform;
            _gameObject = transform.gameObject;
            _sceneObjectList = new List<ISceneObjectEntity>();
            _toRemoveSceneObjectList = new List<ISceneObjectEntity>();
        }

        public override void Dispose()
        {
            for (int i = 0; i < _sceneObjectList.Count; ++i)
            {
                _sceneObjectList[i].Dispose();
            }
            _sceneObjectList = null;
            base.Dispose();
        }

        public void SetLayerOrder(int order)
        {
            _startOrder = order;
            ResetSortingOrder();
        }
        
        public void AddSceneObject(ISceneObjectEntity sceneObject)
        {
            sceneObject.SetParent(_transform);
            sceneObject.SetSortingOrder(GenerateSortingOrder());
            sceneObject.AddListener(SceneObjectEvent.Die, OnSceneObjectDied);
            _sceneObjectList.Add(sceneObject);
        }

        public void RemoveSceneObject(ISceneObjectEntity sceneObject)
        {
            _sceneObjectList.Remove(sceneObject);
            sceneObject.Dispose();
        }

        public void SetTrackCamera(Transform cameraTransform, Bounds sceneBounds)
        {
            _trackCameraTransform = cameraTransform;
            _sceneBounds = sceneBounds;
        }
        
        public void Update(float deltaTime)
        {
            int count = _sceneObjectList.Count;
            for (int i = 0; i < count; ++i)
            {
                _sceneObjectList[i].Update(deltaTime);
            }
            for (int i = 0; i < _toRemoveSceneObjectList.Count; ++i)
            {
                RemoveSceneObject(_toRemoveSceneObjectList[i]);
            }
            _toRemoveSceneObjectList.Clear();
            UpdateTrack();
        }

        private void ResetSortingOrder()
        {
            _curringOrder = _startOrder;
            for (int i = 0; i < _sceneObjectList.Count; ++i)
            {
                _sceneObjectList[i].SetSortingOrder(GenerateSortingOrder());
            }
        }

        private int GenerateSortingOrder()
        {
            _curringOrder += SceneConst.SceneObjectOrderInterval;
            int order = _curringOrder;
            return order;
        }

        private void OnSceneObjectDied(ETEvent evt)
        {
            _toRemoveSceneObjectList.Add(evt.target as ISceneObjectEntity);
        }

        private void UpdateTrack()
        {
            if (_trackCameraTransform != null)
            {
                float offsetX = _trackCameraTransform.localPosition.x;
                float offsetXRate = SceneConst.SceneSpriteOffsetXRate;
                for (int i = _sceneObjectList.Count - 2; i >= 0; --i)
                {
                    ISceneObjectEntity sceneObject = _sceneObjectList[i];
                    if (sceneObject is SceneSpriteGroupEntity)
                    {
                        SceneSpriteGroupEntity spriteGroupEntity = (SceneSpriteGroupEntity)sceneObject;
                        Vector3 localPosition = spriteGroupEntity.transform.localPosition;
                        localPosition.x = offsetX * offsetXRate;
                        spriteGroupEntity.transform.localPosition = localPosition;
                        offsetXRate += offsetXRate;
                    }
                }
            }
        }
    }
}